<template>
  <div class="choose-user">
    <BasicModal
      wrapClassName="choose-user-modal"
      @register="registerModal"
      showFooter
      :title="title"
      :width="width"
      @ok="handleSubmit"
      @cancel="handleClose"
      :show-cancel-btn="false"
      @open-change="handleVisibleChange"
    >
      <div class="page-main">
        <div class="left">
          <!--   :clickRowToExpand="treeCheck" -->
          <BasicTree
            search
            show-icon
            defaultExpandAll
            :check-strictly="treeCheck"
            :checkable="treeCheck"
            treeWrapperClassName="h--[calc(100vh-500px)] overflow-auto"
            :treeData="treeData"
            :checkedKeys="selectedKeys"
            :fieldNames="{ key: 'id', title: 'name' }"
            @select="handleTreeSelect"
            @check="handleTreeCheck"
            ref="asyncExpandTreeRef"
          >
            <template #icon="{ level }">
              <img :src="level_1" v-if="[0, 1].includes(level)" />
              <img :src="level_3" v-else-if="level === 2" />
            </template>
          </BasicTree>
        </div>
        <template v-if="type !== 3">
          <!-- 仅用户 -->
          <div class="mid">
            <div class="mid-top">
              <div>
                <a-input
                  placeholder="请输入名称"
                  v-model:value="searchText"
                  allowClear
                  @change="handleSearchChange"
                >
                  <template #prefix>
                    <img :src="searchIcon" style="width: 14px" />
                  </template>
                </a-input>
              </div>
              <div class="check-box" @click="clickCheckAll">
                <span>全选</span>
                <div> <img :src="checkedAllSrc" /> </div
              ></div>
            </div>
            <div class="overscroll-box">
              <template v-if="selectDeptId || searchAllUser">
                <div class="person-box" v-if="userList.length">
                  <div
                    class="item"
                    v-for="item in userList"
                    :key="item.userId"
                    @click="setItemChecked(item)"
                  >
                    <span>{{ onlyreadCheck === 'user' ? item.name : item.roleName }}</span>
                    <div class="check-box">
                      <img :src="getItemChecked(item)" />
                    </div>
                  </div>
                </div>
                <div class="no-data" v-else>暂无数据</div>
              </template>
              <div class="no-data" v-else>请先选择左侧部门！</div>
            </div>
            <div class="mid-bottom">
              <div class="check-item" @click="onlyread('user')">
                <div>
                  <img :src="onlyreadCheck === 'user' ? checked : checkEmpty" />
                </div>
                <span>只看用户</span>
              </div>
              <div class="check-item" style="cursor: default"> </div>

              <div class="check-item" @click="handleSearchAll">
                <div>
                  <img :src="searchAllUser ? checked : checkEmpty" />
                </div>
                <span>查询所有用户</span>
              </div>
              <div class="check-item" @click="handleByName">
                <div>
                  <img :src="byName ? checked : checkEmpty" />
                </div>
                <span>按名称排名</span>
              </div>
            </div>
          </div>

          <!-- 已选数据展示 -->
          <div class="right">
            <div class="top" v-if="selectedUsers.length">
              <div class="item" v-for="item in selectedUsers" :key="item.userId">
                <span>{{
                  onlyreadCheck === 'user' ? filterName(item.name) : filterName(item.roleName)
                }}</span>
                <div class="close-btn" @click="deleteUser(item)">
                  <img :src="closeImg" />
                </div>
              </div>
            </div>
            <div v-else class="please-choose-person"
              >请选择{{ onlyreadCheck === 'user' ? '用户' : '角色' }}！</div
            >

            <div class="bottom">
              <div class="bottom-left">
                已选
                <span style="color: rgba(43, 99, 161, 1)">{{ selectedUsers.length }}</span
                >个{{ onlyreadCheck === 'user' ? '用户' : '角色' }}
              </div>
              <div @click="clearAllSelected" class="clear-all">清空</div>
            </div>
          </div>
        </template>
      </div>
    </BasicModal>

    <Select
      v-bind="$attrs"
      :class="{
        'HChooseUser-tag': !disabled,
      }"
      placeholder="请选择"
      mode="tags"
      :token-separators="[',']"
      v-model:value="activeKeys"
      disabled
      @click="showModal"
    />
  </div>
</template>
<script lang="ts" setup name="HChooseUser">
  import { withDefaults, ref, computed, unref, nextTick, toRefs, watch } from 'vue';
  import { Select } from 'ant-design-vue';

  import searchIcon from '/@/assets/images/search-icon.png';
  import checkEmpty from '/@/assets/images/check-empty.png';
  import checked from '/@/assets/images/checked.png';
  import indeterminate from '/@/assets/images/indeterminate.png';
  import level_1 from '/@/assets/images/choose-person-level-1.png';
  import level_3 from '/@/assets/images/choose-person-level-3.png';
  import closeImg from '/@/assets/images/close-blue.png';
  import { BasicModal, useModal } from '/@/components/Modal';
  import { TreeDataItem } from 'ant-design-vue/es/tree/Tree';
  import { BasicTree, TreeActionType } from '/@/components/Tree';
  import { debounce, cloneDeep } from 'lodash-es';

  import { getAddressList, getAddressUserList } from '/@/api/admin/userDept';
  import { AddressUserListParams } from '/@/api/admin/model/systemModel';
  import { isArray } from '/@/utils/is';

  import { useMessage } from '/@/hooks/web/useMessage';
  // import { useRuleFormItem } from '/@/hooks/component/useFormItem';

  enum ParamsObj {
    deptIdList = 14,
    userRoleIdList,
    postIdList,
    userIdList,
  }

  const props = withDefaults(
    defineProps<{
      fullPath?: boolean;
      value?: Recordable[] | null | '';
      disabled?: boolean;
      type?: number;
      minSelect?: number;
      maxSelect?: number;
      ids?: string[];
    }>(),
    {
      fullPath: false,
      value: () => [],
      type: 0,
      minSelect: 0,
      maxSelect: Infinity,
      ids: () => [],
    },
  );

  const { fullPath } = toRefs(props);
  const { createMessage } = useMessage();
  const treeData = ref<Array<TreeDataItem>>([]);
  const userList = ref<Array<any>>([]);
  const onlyreadCheck = ref('user');
  const searchAllUser = ref(false);
  const selectDeptId = ref('');
  const byName = ref(false);
  const asyncExpandTreeRef = ref<Nullable<TreeActionType>>(null);
  const searchText = ref('');
  const selectedKeys = ref<any>([]);

  const checkedAllSrc = computed(() => {
    if (!userList.value.length) return checkEmpty;
    const checkedMap: boolean[] = [];
    userList.value.forEach((item) => {
      const find = getFindItem(item);
      checkedMap.push(find ? true : false);
    });
    const allChecked = checkedMap.every((item) => item);
    const allUnChecked = checkedMap.every((item) => !item);
    return allChecked ? checked : allUnChecked ? checkEmpty : indeterminate;
  });

  const title = computed(() => (props.type === 3 ? '部门选择' : '人员选择'));
  const width = computed(() => {
    if (props.type === 3) return '480px';
    return '50%';
  });

  const treeCheck = computed(() => props.type === 3);
  const activeKeys = ref<string[]>([]);
  const emit = defineEmits(['update:value', 'change']);

  const selectedUsers = ref<any>([]);
  const selectedDepts = ref<any>([]);
  let setItem: any[] = [];

  const filterName = (data: string | undefined) => {
    let str = data;
    if (data) {
      const strArr = data.split('-');
      str = strArr[strArr.length - 1];
    }
    return str;
  };
  watch(
    () => props.value,
    (v) => {
      console.log(`v--------------`, v);
      if (v) {
        const data = isArray(v) ? v : [];
        if (props.type === 3) {
          selectedDepts.value = data;
        } else {
          setItem = data;
        }
        activeKeys.value = data.map((el) => el.name);
      }
    },
    {
      immediate: true,
    },
  );
  const [registerModal, { openModal, closeModal }] = useModal();

  function getFindItem(item, type = 'find') {
    return selectedUsers.value[type]((user) => {
      if (hasProperty(user, 'roleId')) return user.roleId == item.roleId;
      return user.userId == item.userId;
    });
  }

  function handleTreeCheck(_, { node }) {
    let Ptitle = getParentTitle(node);

    if (node.checked) {
      selectedDepts.value = selectedDepts.value.filter((i) => i.id !== node.id);
    } else {
      selectedDepts.value.push({
        id: node.id,
        name: unref(fullPath) ? `${Ptitle.join('-')}` : node.title,
      });
      selectedDepts.value = [...new Set(selectedDepts.value.map((i) => JSON.stringify(i)))].map(
        (i) => JSON.parse(i as string),
      );
    }
  }

  function getParentTitle(node) {
    let Ptitle: string[] = [];
    const recursionTitle = (node) => {
      node.title && Ptitle.unshift(node.title);
      if (node.parent) {
        node.parent.node.title && Ptitle.unshift(node.parent.node.title);

        node.parent.parent && recursionTitle(node.parent);
      } else {
        node.node && Ptitle.unshift(node.node.title);
      }
      return Ptitle;
    };
    recursionTitle(node);
    return Ptitle;
  }

  function handleTreeSelect(key, { node }) {
    let Ptitle = getParentTitle(node);

    if (props.type === 3) {
      return;
    }
    searchAllUser.value = false;
    selectDeptId.value = key[0];
    if (!key[0]) return;
    commonRequest(key[0], Ptitle);
  }

  function showModal() {
    if (props.disabled) return;
    openModal();
    nextTick(() => {
      getTree()?.expandAll(true);
      if (props.type === 3) {
        console.log(props.value);
        selectedKeys.value = props.value?.map((el) => el.id) || [];
      } else {
        selectedUsers.value = cloneDeep(setItem);
      }
    });
  }

  function handleSubmit() {
    let data = cloneDeep(unref(selectedDepts));

    if (props.type !== 3) {
      data = cloneDeep(unref(selectedUsers));
      if (unref(fullPath)) {
        data = data.map((i) => {
          return { ...i, name: i.parentTitle || i.name };
        });
      }
    }

    activeKeys.value = data.map((i) => i.name);
    setItem = data;
    emit('change', data);
    emit('update:value', data);
    closeModal();
  }

  function handleClose() {
    closeModal();
  }

  function arrayFlagLevel(array, level) {
    if (!array || !array.length) return;
    array.forEach((item) => {
      item.level = level;
      item.title = item.name;
      if (item.children && item.children.length) {
        arrayFlagLevel(item.children, level + 1);
      }
    });
  }

  function setItemChecked(item) {
    const findIndex = getFindItem(item, 'findIndex');
    if (findIndex > -1) {
      selectedUsers.value.splice(findIndex, 1);
    } else {
      const max = props.maxSelect;

      if (max > 0 && selectedUsers.value.length >= max) {
        createMessage.warn(`最多选择${max}个岗位人员！`);
      } else {
        selectedUsers.value.push(item);
      }
    }
  }

  function hasProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  }

  function getItemChecked(item) {
    const find = getFindItem(item);
    return find ? checked : checkEmpty;
  }

  async function commonRequest(deptId = '', parentTitle?: string[]) {
    const params: AddressUserListParams = {
      deptId,
      addressType: props.type,
    };
    if (byName.value) {
      params.nameSort = 0;
    }
    const res = await getAddressUserList(params);
    userList.value =
      onlyreadCheck.value === 'user'
        ? setParentTitle(res.list, parentTitle, 'user')
        : setParentTitle(res.roleVOS, parentTitle);
    // userList.value = onlyreadCheck.value === 'user' ? res.list : res.roleVOS;
  }

  function setParentTitle(data, parentTitle, type = 'user') {
    let checkData = data;
    if (parentTitle) {
      checkData = data.map((i) => {
        return {
          ...i,
          parentTitle:
            type == 'user'
              ? `${parentTitle.join('-')}-${i.name}`
              : `${parentTitle.join('-')}-${i.roleName}`,
        };
      });
    }
    return checkData;
  }

  const handleSearchChange = debounce(() => {
    searchText.value = searchText.value.trim();
    if (!selectDeptId.value && !searchAllUser.value) return;
    const deptId = searchAllUser.value ? '' : selectDeptId.value;
    commonRequest(deptId);
  }, 500);

  function getTree() {
    const tree = unref(asyncExpandTreeRef);
    if (!tree) {
      throw new Error('tree is null!');
    }
    return tree;
  }

  function handleSearchAll() {
    searchAllUser.value = !searchAllUser.value;
    if (searchAllUser.value) {
      selectDeptId.value = '';
      getTree().setSelectedKeys([]);
      commonRequest();
    }
  }

  function deleteUser(item) {
    const findIndex = getFindItem(item, 'findIndex');
    selectedUsers.value.splice(findIndex, 1);
  }

  function handleByName() {
    byName.value = !byName.value;
    if (!selectDeptId.value && !searchAllUser.value) return;
    const deptId = searchAllUser.value ? '' : selectDeptId.value;
    commonRequest(deptId);
  }

  async function onlyread(type) {
    if (onlyreadCheck.value != type) {
      onlyreadCheck.value = type;
      selectedUsers.value = [];
    }
    if (!selectDeptId.value && !searchAllUser.value) return;
    const deptId = searchAllUser.value ? '' : selectDeptId.value;
    commonRequest(deptId);
  }

  async function getAddressListFn() {
    const params = {
      addressType: props.type,
    };

    if (ParamsObj[props.type]) {
      params[ParamsObj[props.type]] = props.ids;
    }

    if ([10, 11, 12, 13].includes(props.type)) {
      params['deptId'] = props.ids[0];
    }
    const data = await getAddressList(params);
    arrayFlagLevel(data, 0);
    treeData.value = data;
    nextTick(() => {
      unref(asyncExpandTreeRef)?.expandAll(true);
    });
  }

  function clickCheckAll() {
    if ([indeterminate, checkEmpty].includes(checkedAllSrc.value)) {
      try {
        userList.value.forEach((item) => {
          if (selectedUsers.value.length >= 10) throw 'max';
          const find = getFindItem(item);
          if (!find) selectedUsers.value.push(item);
        });
      } catch (res) {
        if (res === 'max') createMessage.warn('最多选择10个岗位人员！');
      }
    } else {
      userList.value.forEach((item) => {
        const findIndex = getFindItem(item, 'findIndex');
        if (findIndex > -1) selectedUsers.value.splice(findIndex, 1);
      });
    }
  }

  function clearAllSelected() {
    selectedUsers.value = [];
  }

  async function handleVisibleChange(visible) {
    if (visible) {
      await getAddressListFn();
      searchAllUser.value = false;
      selectDeptId.value = '';
      onlyreadCheck.value = 'user';
      userList.value = [];
    } else {
      selectedKeys.value = [];
    }
  }
</script>

<style scoped lang="less">
  .page-main {
    border-radius: 2px 2px 2px 2px;
    border: 1px solid #e9e9e9;
    display: flex;
    max-height: calc(100vh - 435px);

    .left {
      flex: 1;
      border-right: 1px solid #e9e9e9;
      padding: 12px;
      overflow-y: auto;

      .tree-box {
        margin-top: 8px;
      }
    }

    .mid {
      flex: 1;
      border-right: 1px solid #e9e9e9;
      display: flex;
      flex-direction: column;
      justify-content: space-between;

      &-top {
        display: flex;
        justify-content: space-between;
        margin-bottom: 18px;
        padding: 12px 12px 0 8px;

        .check-box {
          display: flex;
          align-items: center;
          cursor: pointer;
          user-select: none;

          span {
            margin-right: 8px;
          }
        }
      }

      .overscroll-box {
        flex: 1;
        // height: 400px;
        overflow-y: auto;

        .person-box {
          cursor: pointer;
          padding: 0 12px;
          user-select: none;

          .item {
            display: flex;
            justify-content: space-between;
            // padding: 9px 0 9px 4px;
            min-height: 32px;
            align-items: center;
            margin-bottom: 8px;

            span {
              flex: 1;
              margin-right: 8px;
            }
          }
        }

        .no-data {
          height: 100%;
          width: 100%;
          display: flex;
          justify-content: center;
          align-items: center;
        }
      }

      &-bottom {
        display: flex;
        flex-wrap: wrap;

        width: 100%;

        .check-item {
          height: 36px;
          width: 50%;
          display: flex;
          align-items: center;
          padding: 12px;
          cursor: pointer;
          user-select: none;

          &:nth-child(1) {
            border: 1px solid #e9e9e9;
            border-left: none;
          }

          &:nth-child(2) {
            border: 1px solid #e9e9e9;
            border-left: none;
            border-right: none;
          }

          &:nth-child(3) {
            border-right: 1px solid #e9e9e9;
          }

          div {
            margin-right: 8px;
          }
        }
      }
    }

    .right {
      flex: 1;
      display: flex;
      flex-direction: column;
      justify-content: space-between;

      .top {
        flex: 1;
        overflow-y: auto;
        padding: 12px 12px 0 12px;

        .item {
          height: 32px;
          padding: 9px 12px;
          background: rgba(43, 99, 161, 0.05);
          border-radius: 2px 2px 2px 2px;
          border: 1px solid rgba(43, 99, 161, 0.3);
          display: flex;
          justify-content: space-between;
          align-items: center;
          margin-bottom: 8px;

          .close-btn {
            cursor: pointer;
          }

          span {
            color: rgba(43, 99, 161, 1);
          }
        }
      }

      .please-choose-person {
        flex: 1;
        display: flex;
        justify-content: center;
        align-items: center;
        padding-top: 25px;
      }

      .bottom {
        display: flex;
        height: 37px;
        border-top: 1px solid #e9e9e9;
        justify-content: space-between;
        align-items: center;
        padding: 12px;
        color: rgba(43, 99, 161, 1);

        .bottom-left {
          color: #999999;
        }

        .clear-all {
          cursor: pointer;
        }
      }
    }
  }

  ::v-deep(.vben-tree-header) {
    border-bottom: none;
    padding: 0 0 10px 0;
  }

  ::v-deep(.HChooseUser-tag) {
    &.ant-select-disabled {
      .ant-select-selector {
        cursor: pointer !important;
        background: @component-background !important;

        input,
        .ant-select-selection-item {
          cursor: pointer !important;
        }
      }
    }
  }
</style>

<style lang="less">
  .choose-user-modal {
    .scroll-container {
      .scrollbar__wrap {
        margin-bottom: 0 !important;
      }
    }
  }
</style>
